package com.cnswhy.cloud.server.app.controller.spell;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeWapPayModel;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cnswhy.cloud.common.core.exception.BizException;
import com.cnswhy.cloud.common.core.mybatis.conditions.Wraps;
import com.cnswhy.cloud.common.core.utils.CnswhyUtil;
import com.cnswhy.cloud.common.core.utils.Kits;
import com.cnswhy.cloud.common.core.utils.SystemClockUtil;
import com.cnswhy.cloud.common.logging.uitls.MDCUtil;
import com.cnswhy.cloud.common.rabbitmq.service.MessageService;
import com.cnswhy.cloud.common.redis.service.IdGeneratorService;
import com.cnswhy.cloud.common.redis.service.RedisService;
import com.cnswhy.cloud.server.app.annotation.NotDuplicate;
import com.cnswhy.cloud.server.app.config.JsApiPay;
import com.cnswhy.cloud.server.app.config.WxPayApi;
import com.cnswhy.cloud.server.app.config.WxPayData;
import com.cnswhy.cloud.server.app.controller.BaseController;
import com.cnswhy.cloud.server.app.utils.RSAUtils;
import com.cnswhy.cloud.server.common.entity.constant.AmqpExchange;
import com.cnswhy.cloud.server.common.entity.enumeration.*;
import com.cnswhy.cloud.server.common.entity.mq.OrderQueryMQ;
import com.cnswhy.cloud.server.common.entity.mq.SpellMsg;
import com.cnswhy.cloud.server.core.channel.service.AliRoutePayService;
import com.cnswhy.cloud.server.core.config.AlipayConfig;
import com.cnswhy.cloud.server.core.constant.RedisConstant;
import com.cnswhy.cloud.server.core.entity.*;
import com.cnswhy.cloud.server.core.oem.OemService;
import com.cnswhy.cloud.server.core.query.QueryGenerator;
import com.cnswhy.cloud.server.core.service.CustomerLuckCountService;
import com.cnswhy.cloud.server.core.service.SysConfigService;
import com.cnswhy.cloud.server.core.service.customer.CouponDetailService;
import com.cnswhy.cloud.server.core.service.customer.CustomerPrivilegeService;
import com.cnswhy.cloud.server.core.service.customer.CustomerService;
import com.cnswhy.cloud.server.core.service.shop.ShopProductService;
import com.cnswhy.cloud.server.core.service.shop.ShopProductStockService;
import com.cnswhy.cloud.server.core.service.spell.SpellOrderService;
import com.cnswhy.cloud.server.core.service.spell.SpellPriceService;
import com.cnswhy.cloud.server.core.shop.ProductStockService;
import com.cnswhy.cloud.server.core.utils.PasswordCoder;
import com.cnswhy.cloud.server.core.vo.RespVo;
import com.cnswhy.cloud.server.core.wallet.WalletService;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import lombok.var;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.util.*;

@Controller
@RequestMapping("/spell")
@Slf4j
public class SpellController extends BaseController {
    @Autowired
    IdGeneratorService idGeneratorService;

    @Autowired
    private ShopProductService shopProductService;

    @Autowired
    private CustomerPrivilegeService customerPrivilegeService;

    @Autowired
    private RedisService redisService;

    @Autowired
    private CustomerService customerService;

    @Autowired
    private SpellOrderService spellOrderService;

    @Autowired
    private SpellPriceService spellPriceService;

    @Autowired
    private CouponDetailService couponService;

    @Autowired
    private ShopProductStockService shopProductStockService;
    @Autowired
    private WalletService walletService;
    @Autowired
    private MessageService messageService;
    @Autowired
    SysConfigService sysConfigService;
    @Autowired
    OemService oemService;
    @Autowired
    CustomerLuckCountService customerLuckCountService;
    @Autowired
    ProductStockService productStockService;
    @Autowired
    AliRoutePayService aliRoutePayService;

    @RequestMapping("/ajaxSuccessSpell")
    @ResponseBody
    public RespVo ajaxSuccessSpell() {
        RespVo vo = new RespVo();
        try {
            SpellOrder bo = new SpellOrder();
            bo.setStatus(3);
            QueryWrapper<SpellOrder> queryWrapper = QueryGenerator.initQueryWrapper(bo);
            queryWrapper.orderByDesc("create_time");
            Page<SpellOrder> page = new Page<>(1, 10);
            IPage<SpellOrder> pageList = spellOrderService.page(page, queryWrapper);
            JSONObject jsonPage = JSON.parseObject(JSON.toJSONString(pageList));
            JSONArray jsonArray = new JSONArray();
            for (var var : pageList.getRecords()) {
                JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(var));
                SpellPrice spellPrice = spellPriceService.getById(var.getPriceId());
                if (spellPrice == null) {
                    continue;
                }
                ShopProduct shopProduct = shopProductService.getById(var.getProductId());
                if (shopProduct == null) {
                    continue;
                }
                jsonObject.put("priceTitle", spellPrice.getTitle());
                jsonObject.put("productName", shopProduct.getProductName());
                jsonObject.put("productImg", shopProduct.getThumbnailImg());
                jsonArray.add(jsonObject);
            }
            jsonPage.put("records", jsonArray);
            vo.setCode(RespVo.CODE_SUCCESS);
            vo.setResult(jsonPage);
        } catch (Exception e) {
            vo.setCode(RespVo.CODE_ERROR);
            vo.setMessage("查询拼团成功列表失败");
            log.error("查询拼团成功列表失败", e);
        }
        return vo;
    }

    @RequestMapping("/getEndTime")
    @ResponseBody
    public RespVo getEndTime() {
        RespVo vo = new RespVo();
        try {
            String time = (String) redisService.hget(RedisConstant.SYS_CONFIG_2, RedisConstant.SPELL_START_END_TIME);
            vo.setCode(RespVo.CODE_SUCCESS);
            vo.setResult(time.split("-")[1]);
        } catch (Exception e) {
            vo.setCode(RespVo.CODE_ERROR);
            vo.setMessage("查询交易时间失败");
            log.error("查询交易时间失败", e);
        }
        return vo;
    }

    /**
     * 我要发货和我要回购
     *
     * @param id
     * @param goodsType
     * @return
     */
    @RequestMapping("/updateGoodsType")
    @ResponseBody
    public RespVo updateGoodsType(Long id, Integer goodsType) {
        RespVo vo = new RespVo();
        try {
            if(oemService.isPintuanmao() && goodsType.equals(Integer.valueOf(1))){
                vo.setCode(RespVo.CODE_ERROR);
                vo.setMessage("该订单不能操作回购");
                return vo;
            }
            // 回购
            SpellOrder order = new SpellOrder();
            order = spellOrderService.getById(id);
            if(Integer.valueOf(2).equals(order.getStatus())){
                vo.setCode(RespVo.CODE_ERROR);
                vo.setMessage("拼团中不能发起回购");
                return vo;
            }
            if(Integer.valueOf(1).equals(order.getGoodsType()) || Integer.valueOf(2).equals(order.getGoodsType())){
                vo.setCode(RespVo.CODE_ERROR);
                vo.setMessage("该订单已经操作，请勿重复操作");
                return vo;
            }
            /*if(order.getGoodsType().equals(1) || order.getGoodsType().equals(2)){
                vo.setCode(RespVo.CODE_ERROR);
                vo.setMessage("该订单已经操作，请勿重复操作");
                return vo;
            }*/
            order.setGoodsType(goodsType);
            if (goodsType == 1) {
                String time = (String) redisService.hget(RedisConstant.SYS_CONFIG_2,
                        RedisConstant.SPELL_START_END_TIME);
                String[] split = time.split("-");
                Calendar instance = Calendar.getInstance();
                int hour = instance.get(Calendar.HOUR_OF_DAY);
                int minute = hour * 60 + instance.get(Calendar.MINUTE);
                if (Integer.valueOf(split[0]) > minute || Integer.valueOf(split[1]) < minute) {
                    vo.setCode(RespVo.CODE_ERROR);
                    vo.setMessage("不在回购时间范围");
                    return vo;
                }
                if(Integer.valueOf(4).equals(order.getSendStatus()) || Integer.valueOf(5).equals(order.getSendStatus()) ){
                    vo.setCode(RespVo.CODE_ERROR);
                    vo.setMessage("已经代卖中，或者已经回购完成，请勿重复操作");
                    return vo;
                }
                /*if (Integer.valueOf(1).equals(order.getGoodsType())) {
                    vo.setCode(RespVo.CODE_ERROR);
                    vo.setMessage("已经代卖中");
                    return vo;
                }*/
                order.setSendStatus(4);
            } else if(goodsType == 2) {
                order.setSendStatus(1);
            }else{
                vo.setCode(RespVo.CODE_ERROR);
                vo.setMessage("无效操作类型");
                return vo;
            }
            spellOrderService.updateById(order);
        } catch (Exception e) {
            vo.setCode(RespVo.CODE_ERROR);
            vo.setMessage("操作失败");
        }
        return vo;
    }

    /**
     * 查询我的拼团订单
     *
     * @param bo
     * @param request
     * @return
     */
    @RequestMapping("/ajaxSpellOrder")
    @ResponseBody
    public RespVo ajaxSpellOrder(SpellOrder bo, HttpServletRequest request,
                                 @RequestParam(name = "currentPage", defaultValue = "1") Integer currentPage,
                                 @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize) {
        RespVo vo = new RespVo();
        try {
            Customer loginCustomer = getLoginCustomer( request);
            bo.setCustomerId(loginCustomer.getId());
            QueryWrapper<SpellOrder> queryWrapper = null;
            if (bo.getStatus() != null && bo.getStatus() == 6) {
                List<Integer> statusList = new ArrayList<Integer>();
                statusList.add(3);
                statusList.add(4);
                bo.setStatus(null);
                queryWrapper = QueryGenerator.initQueryWrapper(bo);
                queryWrapper = queryWrapper.in("status", statusList);
            } else {
                if ((bo.getStatus() != null && bo.getStatus() == 3)) {
                    queryWrapper = QueryGenerator.initQueryWrapper(bo);
                    if(bo.getSendStatus() == null){
                        queryWrapper = queryWrapper.isNull("send_status");
                    }
                } else {
                    queryWrapper = QueryGenerator.initQueryWrapper(bo);
                }
            }
            queryWrapper = queryWrapper.orderByDesc("id");
            Page<SpellOrder> page = new Page<>(currentPage, pageSize);
            IPage<SpellOrder> pageList = spellOrderService.page(page, queryWrapper);
            JSONObject jsonPage = JSON.parseObject(JSON.toJSONString(pageList));
            JSONArray jsonArray = new JSONArray();
            String pfx = String.valueOf(redisService.hget(RedisConstant.SYS_CONFIG_1, RedisConstant.FTP_PATH_PREFIX));
            for (var var : pageList.getRecords()) {
                JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(var));
                SpellPrice spellPrice = spellPriceService.getById(var.getPriceId());
                if (spellPrice == null) {
                    continue;
                }
                ShopProduct shopProduct = shopProductService.getById(var.getProductId());
                if (shopProduct == null) {
                    continue;
                }
                jsonObject.put("priceTitle", spellPrice.getTitle());
                jsonObject.put("productName", shopProduct.getProductName());
                if(StringUtils.isNotBlank(shopProduct.getUrl())){
                    jsonObject.put("productImg", shopProduct.getUrl());
                }else{
                    jsonObject.put("productImg", pfx + shopProduct.getThumbnailImg());
                }

                jsonArray.add(jsonObject);
            }
            jsonPage.put("records", jsonArray);
            vo.setCode(RespVo.CODE_SUCCESS);
            vo.setResult(jsonPage);
            //vo.setCode(RespVo.CODE_SUCCESS);
            //vo.setResult(pageList);
        } catch (Exception e) {
            vo.setCode(RespVo.CODE_ERROR);
            vo.setMessage("查询我的参团失败");
            log.error("查询我的参团失败", e);
        }
        return vo;
    }

    @RequestMapping("/queryMyCoupon")
    @ResponseBody
    public RespVo queryMyCoupon(Long stockId, HttpServletRequest request) {
        RespVo vo = new RespVo();
        try {
            ShopProductStock queryStockById = shopProductStockService.getById(stockId);
            ShopProduct productEntity = shopProductService.getById(queryStockById.getProductId());
            Customer loginCustomer = getLoginCustomer( request);
            int queryCanUse = customerPrivilegeService.queryCanUse(productEntity.getPriceId(), loginCustomer.getId());
            vo.setCode(RespVo.CODE_SUCCESS);
            vo.setResult(queryCanUse);
        } catch (Exception e) {
            vo.setCode(RespVo.CODE_ERROR);
            vo.setMessage("查询失败");
            log.error("查询失败", e);
        }
        return vo;
    }
    @RequestMapping("/queryLuckyCount")
    @ResponseBody
    public RespVo queryLuckyCount(Long stockId, HttpServletRequest request, String type) {
        RespVo vo = new RespVo();
        try {
            if (StringUtils.isBlank(type)) {
                type = "1";
            }
            Customer loginCustomer = getLoginCustomer( request);
            if ("1".equals(type)) {
                ShopProductStock queryStockById = shopProductStockService.getById(stockId);
                ShopProduct productEntity = shopProductService.getById(queryStockById.getProductId());
                //int queryCanUse = customerPrivilegeService.queryCanUse(productEntity.getPriceId(), loginCustomer.getId());
                CustomerLuckCount customerLuckCount = customerLuckCountService.getOne(Wraps.<CustomerLuckCount>lbQ()
                        .eq(CustomerLuckCount::getCustomerId, loginCustomer.getId())
                        .eq(CustomerLuckCount::getPriceId, productEntity.getPriceId()));
                if (customerLuckCount == null) {
                    customerLuckCount = new CustomerLuckCount();
                    customerLuckCount.setCustomerId(loginCustomer.getId());
                    customerLuckCount.setPriceId(productEntity.getPriceId());
                    customerLuckCount.setValue(99);
                    customerLuckCount.setResetCount(0);
                    customerLuckCountService.save(customerLuckCount);
                }
                vo.setResult(customerLuckCount.getValue());
            } else {
                List<CustomerLuckCount> customerLuckCountList = customerLuckCountService.getLuckCountList(loginCustomer.getId().toString());
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("pageList", customerLuckCountList);
                vo.setResult(jsonObject);
            }
            vo.setCode(RespVo.CODE_SUCCESS);

        } catch (Exception e) {
            vo.setCode(RespVo.CODE_ERROR);
            vo.setMessage("查询失败");
            log.error("查询失败", e);
        }
        return vo;
    }

    /**
     * 参与拼团
     *
     * @param stockId
     * @param payType
     * @param tradePass
     * @param addressId
     * @param request
     * @return
     */
    @SuppressWarnings("unchecked")
    @RequestMapping("/joinSpell")
    @NotDuplicate
    @ResponseBody
    public RespVo joinSpell(Long stockId, Integer payType, String tradePass, Long addressId, HttpServletRequest request) {
        log.info("加入拼团:{} {} {} {}", stockId, payType, addressId);
        RespVo vo = new RespVo();
        try {
            ShopProductStock queryStockById = shopProductStockService.getById(stockId);
            ShopProduct productEntity = shopProductService.getById(queryStockById.getProductId());
            if (productEntity == null) {
                vo.setCode(RespVo.CODE_ERROR);
                vo.setMessage("未找到拼团商品信息");
                return vo;
            }
            String flag = (String) redisService.hget(RedisConstant.SYS_CONFIG_2, RedisConstant.shop_product_spell_flag);
            if("true".equals(flag) && Integer.valueOf(1).equals(productEntity.getSpellProduct())){
                vo.setCode(RespVo.CODE_ERROR);
                vo.setMessage("商品已抢光！");
                return vo;
            }
            String time = (String) redisService.hget(RedisConstant.SYS_CONFIG_2, RedisConstant.SPELL_START_END_TIME);
            String[] split = time.split("-");
            Calendar instance = Calendar.getInstance();
            int hour = instance.get(Calendar.HOUR_OF_DAY);
            int minute = hour * 60 + instance.get(Calendar.MINUTE);
            if (Integer.valueOf(split[0]) > minute || Integer.valueOf(split[1]) < minute) {
                vo.setCode(RespVo.CODE_ERROR);
                vo.setMessage("不在拼购时间范围");
                return vo;
            }
            Customer loginCustomer = getLoginCustomer( request);
            Customer customer = customerService.queryById(loginCustomer.getId());
            //强制拼团需要实名
            if (oemService.isLeyoutuan()) {
                //强制同名提现
                if (!("1".equals(customer.getVerifyStatus()))) {
                    vo.setCode(RespVo.VALIDATE_ERROR);
                    vo.setMessage("未实名不能拼团！");
                    return vo;
                }
            }
            // 拼购券支付
            if (payType == 1) {
                if (StringUtils.isEmpty(tradePass)) {
                    vo.setCode(RespVo.CODE_ERROR);
                    vo.setMessage("请输入交易密码");
                    return vo;
                }

                String password = null;
                password = RSAUtils.decryptString(tradePass);// 解密
                if (!StringUtils.equals(PasswordCoder.generatePassword(password), customer.getTradePass())) {
                    vo.setCode(RespVo.CODE_ERROR);
                    vo.setMessage("交易密码错误");
                    return vo;
                }
                SpellOrder orderBo = new SpellOrder();
                orderBo.setPriceId(productEntity.getPriceId());
                orderBo.setCustomerId(loginCustomer.getId());
                // 判断是否已经超过设定的次数
                int queryCustomerSpellOrder = spellOrderService.queryCustomerSpellOrder(orderBo);
                SpellPrice queryById = spellPriceService.getById(productEntity.getPriceId());
                if (queryCustomerSpellOrder >= queryById.getJoinNum()) {
                    vo.setCode(RespVo.CODE_ERROR);
                    vo.setMessage("该拼团区间今天已经达到上限，请选择其他拼购区或者让明天再来吧！");
                    return vo;
                }
                orderBo.setStatus(2);// 是否有进行中的
                orderBo.setSettDate(SystemClockUtil.getSettDateyyyyMMdd());
                QueryWrapper<SpellOrder> queryWrapper = QueryGenerator.initQueryWrapper(orderBo);
                List<SpellOrder> listTodatSpellSuccess = spellOrderService.list(queryWrapper);
                if (listTodatSpellSuccess.size() > 0) {
                    vo.setCode(RespVo.CODE_ERROR);
                    vo.setMessage("该拼团区间已经有订单了，等结束后再来吧");
                    return vo;
                }
                Integer isPrivilege = 2;// 无免中特权
                if(oemService.isChaoRenGou()){ // 潮人海购
                    CustomerLuckCount customerLuckCount = customerLuckCountService.getOne(Wraps.<CustomerLuckCount>lbQ()
                            .eq(CustomerLuckCount::getCustomerId,customer.getId())
                            .eq(CustomerLuckCount::getPriceId,productEntity.getPriceId()));
                    if(customerLuckCount == null){
                        customerLuckCount = new CustomerLuckCount();
                        customerLuckCount.setCustomerId(customer.getId());
                        customerLuckCount.setPriceId(productEntity.getPriceId());
                        customerLuckCount.setValue(99);
                        customerLuckCount.setResetCount(0);
                        customerLuckCountService.save(customerLuckCount);
                    }
                    if(customerLuckCount.getValue() != 99){
                        isPrivilege = 1;// 免中特权
                    }
                }else{
                    int queryCanUse = customerPrivilegeService.queryCanUse(productEntity.getPriceId(),loginCustomer.getId());
                    if (queryCanUse > 0) {
                        isPrivilege = 1;// 免中特权
                    }else{
                        vo.setCode(RespVo.CODE_ERROR);
                        vo.setMessage("无可用拼购券");
                        return vo;
                    }
                }
                try {
                    productStockService.subStock(queryStockById.getId(),Long.valueOf(1));
                } catch (BizException e) {
                    vo.setCode(RespVo.CODE_ERROR);
                    vo.setMessage("抱歉，库存不足");
                    return vo;
                } catch (Exception e){
                    vo.setCode(RespVo.CODE_ERROR);
                    vo.setMessage("系统繁忙，请稍后重试");
                    return vo;
                }
                // 保存客户订单
                SpellOrder order = new SpellOrder();
                order.setCustomerId(customer.getId());
                order.setPriceId(productEntity.getPriceId());
                order.setStatus(2);// 拼团中
                order.setProductId(productEntity.getId());
                order.setPayType(payType);
                order.setStockId(queryStockById.getId());
                order.setOrderPrice(queryStockById.getSellPrice());
                order.setIsPrivilege(isPrivilege);
                order.setPayOrderNum("P" + Kits.Date.getyyyyMMddHHmmss() + Kits.Random.getRandom(1000, 10000));
                order.setAddressId(addressId);
                order.setLoginName(customer.getLoginName());

                order.setSpellOrderId(queryById.getNewSpellOrderId());
                order.setSettDate(SystemClockUtil.getSettDateyyyyMMdd());
                order.setExpressCompany(ExpressCompany.UNKNOWN);
                spellOrderService.save(order);
                CouponDetail detail = new CouponDetail();
                detail.setCustomerId(customer.getId());
                detail.setCouponNum(queryStockById.getSellPrice());
                detail.setType(2);// 参与拼购
                detail.setOrderNum(order.getPayOrderNum());
                couponService.save(detail);
                vo.setCode(RespVo.CODE_SUCCESS);
                vo.setResult(order.getPayOrderNum());
                vo.setMessage("参团成功");
                if(oemService.isChaoRenGou()){
                    SpellMsg spellMsg = SpellMsg.builder().id(order.getId()).build();
                    spellMsg.setTraceId(MDCUtil.getTraceId());
                    messageService.sendQueueByObject(AmqpExchange.CHAOREN_SPELL_MESSAGE, spellMsg);
                }else {
                    SpellMsg spellMsg = SpellMsg.builder().id(order.getId()).build();
                    spellMsg.setTraceId(MDCUtil.getTraceId());
                    messageService.sendQueueByObject(AmqpExchange.SPELL_MESSAGE, spellMsg);
                }
            } else if (payType == 4) {
                if (StringUtils.isEmpty(tradePass)) {
                    vo.setCode(RespVo.CODE_ERROR);
                    vo.setMessage("请输入交易密码");
                    return vo;
                }

                String password = null;
                password = RSAUtils.decryptString(tradePass);// 解密
                if (!StringUtils.equals(PasswordCoder.generatePassword(password), customer.getTradePass())) {
                    vo.setCode(RespVo.CODE_ERROR);
                    vo.setMessage("交易密码错误");
                    return vo;
                }
                CustomerWallet customerWallet = walletService.getCustomerWallet(customer.getId(), WalletType.BALANCE);
                if(!walletService.checkDed(customerWallet.getCustomerId(),WalletType.BALANCE,CnswhyUtil.getFen(queryStockById.getSellPrice()))){
                    vo.setCode(RespVo.CODE_ERROR);
                    vo.setMessage("余额不足");
                    return vo;
                }
                SpellOrder orderBo = new SpellOrder();
                orderBo.setPriceId(productEntity.getPriceId());
                orderBo.setCustomerId(loginCustomer.getId());
                // 判断是否已经超过设定的次数
                int queryCustomerSpellOrder = spellOrderService.queryCustomerSpellOrder(orderBo);
                SpellPrice queryById = spellPriceService.getById(productEntity.getPriceId());
                if (queryCustomerSpellOrder >= queryById.getJoinNum()) {
                    vo.setCode(RespVo.CODE_ERROR);
                    vo.setMessage("该拼团区间今天已经达到上限，请选择其他拼购区或者让明天再来吧！");
                    return vo;
                }
                orderBo.setStatus(2);// 是否有进行中的
                orderBo.setSettDate(SystemClockUtil.getSettDateyyyyMMdd());
                QueryWrapper<SpellOrder> queryWrapper = QueryGenerator.initQueryWrapper(orderBo);
                List<SpellOrder> listTodatSpellSuccess = spellOrderService.list(queryWrapper);
                if (listTodatSpellSuccess.size() > 0) {
                    vo.setCode(RespVo.CODE_ERROR);
                    vo.setMessage("该拼团区间已经有订单了，等结束后再来吧");
                    return vo;
                }
                try {
                    productStockService.subStock(queryStockById.getId(),Long.valueOf(1));
                } catch (BizException e) {
                    vo.setCode(RespVo.CODE_ERROR);
                    vo.setMessage("抱歉，库存不足");
                    return vo;
                } catch (Exception e){
                    vo.setCode(RespVo.CODE_ERROR);
                    vo.setMessage("系统繁忙，请稍后重试");
                    return vo;
                }
                SpellOrder order = new SpellOrder();
                order.setCustomerId(customer.getId());
                order.setPriceId(productEntity.getPriceId());
                order.setStatus(2);// 拼团中
                order.setProductId(productEntity.getId());
                order.setPayType(payType);
                order.setStockId(queryStockById.getId());
                order.setOrderPrice(queryStockById.getSellPrice());
                order.setIsPrivilege(2);
                order.setPayOrderNum("P" + Kits.Date.getyyyyMMddHHmmss() + Kits.Random.getRandom(1000, 10000));
                order.setAddressId(addressId);
                order.setLoginName(customer.getLoginName());
                order.setSettDate(SystemClockUtil.getSettDateyyyyMMdd());
                order.setSpellOrderId(queryById.getNewSpellOrderId());
                order.setExpressCompany(ExpressCompany.UNKNOWN);
                spellOrderService.save(order);
                //walletService.ded(customer.getId(),WalletType.BALANCE, TransType.SPELL_ORDER,CnswhyUtil.getFen(queryStockById.getSellPrice()),order.getPayOrderNum());
                SpellMsg spellMsg = SpellMsg.builder().id(order.getId()).build();
                spellMsg.setTraceId(MDCUtil.getTraceId());
                messageService.sendQueueByObject(AmqpExchange.SPELL_MESSAGE,spellMsg);
            } else {
                // 微信和支付宝支付
                SpellOrder orderBo = new SpellOrder();
                orderBo.setPriceId(productEntity.getPriceId());
                orderBo.setCustomerId(loginCustomer.getId());
                int queryCustomerSpellOrder = spellOrderService.queryCustomerSpellOrder(orderBo);
                SpellPrice queryById = spellPriceService.getById(productEntity.getPriceId());
                if(oemService.isLuyilu()){

                }else {
                    if (queryCustomerSpellOrder >= queryById.getJoinNum()) {
                        vo.setCode(RespVo.CODE_ERROR);
                        vo.setMessage("该拼团区间今天已经达到上限，请选择其他拼购区或者让明天再来吧！");
                        return vo;
                    }
                    orderBo.setStatus(2);// 是否有进行中的
                    orderBo.setSettDate(SystemClockUtil.getSettDateyyyyMMdd());
                    QueryWrapper<SpellOrder> queryWrapper = QueryGenerator.initQueryWrapper(orderBo);
                    List<SpellOrder> listTodatSpellSuccess = spellOrderService.list(queryWrapper);
                    //if (CollectionUtils.isNotEmpty(listTodatSpellSuccess)) {
                    if (listTodatSpellSuccess.size() > 0) {
                        vo.setCode(RespVo.CODE_ERROR);
                        vo.setMessage("该拼团区间已经有订单了，等结束后再来吧");
                        return vo;
                    }
                }

                // 保存客户订单
                try {
                    productStockService.subStock(queryStockById.getId(),Long.valueOf(1));
                } catch (BizException e) {
                    vo.setCode(RespVo.CODE_ERROR);
                    vo.setMessage("抱歉，库存不足");
                    return vo;
                } catch (Exception e){
                    vo.setCode(RespVo.CODE_ERROR);
                    vo.setMessage("系统繁忙，请稍后重试");
                    return vo;
                }
                SpellOrder order = new SpellOrder();
                order.setCustomerId(customer.getId());
                order.setPriceId(productEntity.getPriceId());
                order.setStatus(1);
                order.setProductId(productEntity.getId());
                order.setPayType(payType);
                order.setAddressId(addressId);
                order.setStockId(queryStockById.getId());
                order.setOrderPrice(queryStockById.getSellPrice());
                order.setPayOrderNum("P" + Kits.Date.getyyyyMMddHHmmss() + Kits.Random.getRandom(1000, 10000));
                order.setLoginName(customer.getLoginName());
                order.setSettDate(SystemClockUtil.getSettDateyyyyMMdd());
                order.setSpellOrderId(queryById.getNewSpellOrderId());
                order.setExpressCompany(ExpressCompany.UNKNOWN);
                spellOrderService.save(order);
                vo.setCode(RespVo.CODE_SUCCESS);
                vo.setResult(order.getPayOrderNum());
            }
        } catch (Exception e) {
            vo.setCode(RespVo.CODE_ERROR);
            vo.setMessage("参团失败");
            log.error("参团失败", e);
        }
        return vo;
    }


    @ApiOperation(value = "订单查询")
    @ApiParam(name = "orderNum", value = "订单号")
    @RequestMapping("/orderQuery")
    @ResponseBody
    public RespVo orderQuery(HttpServletRequest request, HttpServletResponse response, String orderNum, String orderId) {
        RespVo respVo = new RespVo();
        SpellOrder order = spellOrderService.getOne(Wraps.<SpellOrder>lbQ().eq(SpellOrder::getPayOrderNum, orderNum));
        if(StringUtils.isBlank(order.getAuthNo())){
            order.setAuthNo(orderId);
            spellOrderService.updateById(order);
        }
        respVo.setResult(order.getOrderPrice());
        if(order.getStatus().intValue() == 0 || order.getStatus().intValue() == 1 ){
            respVo.setCode(RespVo.CODE_ERROR);
            respVo.setMessage("待支付");
        }else{
            respVo.setCode(RespVo.CODE_SUCCESS);
            respVo.setMessage("支付成功");
        }
        return respVo;
    }
    @ApiOperation(value = "商城订单支付宝支付")
    @ApiParam(name = "orderNum", value = "订单号")
    @RequestMapping("/alipayPay")
    @ResponseBody
    public RespVo alipayPay(HttpServletRequest request, HttpServletResponse response, String orderNum) {
        log.info("商城订单支付宝支付:{}", orderNum);

        RespVo respVo = new RespVo();
        try {
            if (StringUtils.isBlank(orderNum)) {
                respVo.setCode(RespVo.CODE_VERIFY);
                respVo.setMessage("参数异常");
                return respVo;
            }
            String flag = (String) redisService.hget(RedisConstant.SYS_CONFIG_2,
                    RedisConstant.ali_route_pay);
            if("true".equals(flag)){
                SpellOrder order = spellOrderService.getOne(Wraps.<SpellOrder>lbQ().eq(SpellOrder::getPayOrderNum, orderNum));

                try {
                    String responseString = aliRoutePayService.pay(order.getPayOrderNum(),CnswhyUtil.getFen(order.getOrderPrice()),"SPELL-SHOPPING");
                    JSONObject jsonObject = JSON.parseObject(responseString);
                    if("0100".equals(jsonObject.getString("code"))){
                        String data = jsonObject.getString("data");
                        JSONObject jsonObject1 = JSON.parseObject(data);
                        respVo.setResult(jsonObject1.getString("html"));
                        respVo.setCode(RespVo.CODE_SUCCESS);
                        OrderQueryMQ orderQueryMQ = OrderQueryMQ.builder().orderId(orderNum).queryTimes(0L).build();
                        orderQueryMQ.setPayType(PayType.alipay);
                        orderQueryMQ.setBody("SPELL-SHOPPING");
                        orderQueryMQ.setTraceId(MDCUtil.getTraceId());
                        messageService.sendAndQueryTimes(AmqpExchange.ORDER_QUERY_MESSAGE, orderQueryMQ, orderQueryMQ.getQueryTimes());
                        return respVo;
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    respVo.setCode(RespVo.CODE_ERROR);
                    respVo.setMessage("调用支付宝发起支付请求异常");
                    return respVo;
                }
            }else{
                String price = "";
                String body = "SPELL-SHOPPING";

                SpellOrder order = spellOrderService.getOne(Wraps.<SpellOrder>lbQ().eq(SpellOrder::getPayOrderNum, orderNum));

                //取库中支付宝参数
                SysConfig sysConfig = sysConfigService.getOne(Wraps.<SysConfig>lbQ().eq(SysConfig::getConfigKey, "aliPaySys").eq(SysConfig::getDisplayStatus, "1"));

                price = order.getOrderPrice().toString();
                AlipayClient client = new DefaultAlipayClient(AlipayConfig.URL, sysConfig.getConfigValue(),
                        sysConfig.getValidateRules(), AlipayConfig.FORMAT, AlipayConfig.CHARSET,
                        sysConfig.getConfigRules(), AlipayConfig.SIGNTYPE);
                // AlipayTradeWapPayRequest alipay_request = new AlipayTradeWapPayRequest();

                AlipayTradeAppPayRequest alipay_request = new AlipayTradeAppPayRequest();
                // 封装请求支付信息
                AlipayTradeWapPayModel model = new AlipayTradeWapPayModel();
                model.setOutTradeNo(orderNum);
                model.setSubject("支付订单" + orderNum);
                model.setTotalAmount(price);
                model.setBody(body);
                model.setTimeoutExpress("2m");
                model.setProductCode("QUICK_MSECURITY_PAY");
                alipay_request.setBizModel(model);


                // 设置异步通知地址
                alipay_request.setNotifyUrl(
                        (String) redisService.hget(RedisConstant.SYS_CONFIG_1, RedisConstant.ALIPAY_NOTIFY_URL));
                // 设置同步地址
                alipay_request.setReturnUrl("http://shop.zhcone.cn/#/pages/tabBar/index");
                AlipayTradeAppPayResponse alipayTradeAppPayResponse = client.sdkExecute(alipay_request);
                // 就是orderString 可以直接给APP请求，无需再做处理。
                String orderString = alipayTradeAppPayResponse.getBody();
                log.error(orderString);

                OrderQueryMQ orderQueryMQ = OrderQueryMQ.builder().orderId(orderNum).queryTimes(0L).build();
                orderQueryMQ.setPayType(PayType.alipay);
                orderQueryMQ.setBody(body);
                orderQueryMQ.setTraceId(MDCUtil.getTraceId());
                messageService.sendAndQueryTimes(AmqpExchange.ORDER_QUERY_MESSAGE, orderQueryMQ, orderQueryMQ.getQueryTimes());
                respVo.setResult(orderString);
                respVo.setCode(0);
            }

        } catch (Exception e) {
            respVo.setCode(RespVo.CODE_ERROR);
            respVo.setMessage("调用支付宝发起支付请求异常");
            log.error("支付宝拉起失败", e);
        }
        return respVo;
    }

    @ApiOperation(value = "拼团订单余额支付")
    @RequestMapping("/DEFAULTPay")
    @ResponseBody
    public RespVo DEFAULTPay(HttpServletRequest request, HttpServletResponse response, String orderNum, String tradePass) {
        log.info("拼团订单余额支付:{}", orderNum);

        RespVo respVo = new RespVo();
        try {
            if (StringUtils.isBlank(orderNum)) {
                respVo.setCode(RespVo.CODE_VERIFY);
                respVo.setMessage("参数异常");
                return respVo;
            }
            SpellOrder order = spellOrderService.getOne(Wraps.<SpellOrder>lbQ().eq(SpellOrder::getPayOrderNum, orderNum));
            if (StringUtils.isEmpty(tradePass)) {
                respVo.setCode(RespVo.CODE_ERROR);
                respVo.setMessage("请输入交易密码");
                return respVo;
            }
            if(oemService.isChaoRenGou()){
                if(order.getSendStatus() != 0){
                    respVo.setCode(RespVo.CODE_ERROR);
                    respVo.setMessage("该订单已经支付，请不要重复支付");
                    return respVo;
                }
            }
            Customer loginCustomer = getLoginCustomer( request);
            Customer customer = customerService.queryById(loginCustomer.getId());
            String password = null;
            password = RSAUtils.decryptString(tradePass);// 解密
            if (!StringUtils.equals(PasswordCoder.generatePassword(password), customer.getTradePass())) {
                respVo.setCode(RespVo.CODE_ERROR);
                respVo.setMessage("交易密码错误");
                return respVo;
            }
            CustomerWallet customerWallet = walletService.getCustomerWallet(customer.getId(), WalletType.BALANCE);
            if(!walletService.checkDed(customerWallet.getCustomerId(),WalletType.BALANCE,CnswhyUtil.getFen(order.getOrderPrice()))){
                respVo.setCode(RespVo.CODE_ERROR);
                respVo.setMessage("余额不足");
                return respVo;
            }
            /*order.setSendStatus(1);
            order.setIsPrivilege(2);
            //order.setTransactionId(outNo);
            spellOrderService.saveOrUpdate(order);*/
            //order = updateOrderSpellOrder(order.getId(),1,2,PayType.balance);
            //walletService.ded(customer.getId(),WalletType.BALANCE, TransType.SPELL_ORDER,CnswhyUtil.getFen(order.getOrderPrice()),order.getPayOrderNum());
            SpellMsg spellMsg = SpellMsg.builder().id(order.getId()).build();
            spellMsg.setTraceId(MDCUtil.getTraceId());
            messageService.sendQueueByObject(AmqpExchange.SPELL_MESSAGE,spellMsg);
            respVo.setCode(0);
        } catch (Exception e) {
            respVo.setCode(RespVo.CODE_ERROR);
            respVo.setMessage("调用余额支付请求异常");
            log.error("调用余额支付请求异常", e);
        }
        return respVo;
    }
    private SpellOrder updateOrderSpellOrder(Long id, int sendStatus, int isPrivilege, PayType payType){
        SpellOrder spellOrder = spellOrderService.getById(id);
        spellOrder.setSendStatus(sendStatus);
        spellOrder.setIsPrivilege(isPrivilege);
        spellOrder.setPayType(payType.getVal());
        //spellOrder.setStatus(2);
        spellOrderService.updateById(spellOrder);
        return spellOrder;
    }

    @ApiOperation(value = "商城订单微信支付", httpMethod = "POST")
    @ApiParam(name = "orderNum", value = "订单号")
    @RequestMapping("/wxPay")
    @ResponseBody
    public RespVo wxPay(String orderNum, String client, HttpServletRequest request) {
        log.info("商城订单微信支付:{}", orderNum);

        RespVo respVo = new RespVo();
        try {

            //取库中微信参数
            SysConfig sysConfig = sysConfigService.getOne(Wraps.<SysConfig>lbQ().eq(SysConfig::getConfigKey, "wxPaySys").eq(SysConfig::getDisplayStatus, "1"));

            BigDecimal price = BigDecimal.ZERO;
            String body = "SPELL-SHOPPING";
            //SpellOrder order = (SpellOrder) redisService.hget(RedisConstant.SPELL_ORDER_WAIT_PAY, orderNum);
            SpellOrder order = spellOrderService.getOne(Wraps.<SpellOrder>lbQ().eq(SpellOrder::getPayOrderNum, orderNum));
            price = order.getOrderPrice();
            BigDecimal multiply = price.multiply(new BigDecimal("100"));
            String notifyUrl = (String) redisService.hget(RedisConstant.SYS_CONFIG_1, RedisConstant.WX_NOTIFY_URL);
            JsApiPay jsApiPay = new JsApiPay(null, multiply.intValue(), sysConfig.getValidateRules(), sysConfig.getConfigValue(),
                    notifyUrl, sysConfig.getConfigRules(), "", "APP");
            WxPayData wxData = jsApiPay.GetUnifiedOrderResult("乐拼团订单", "交易编号：" + orderNum, orderNum, body,CnswhyUtil.getHttpServletRequestIpAddress());
            if (StringUtils.equals(wxData.GetValue("return_code").toString(), "SUCCESS")
                    && StringUtils.equals(wxData.GetValue("result_code").toString(), "SUCCESS")) {
                Date beijingDate = Calendar.getInstance(Locale.CHINA).getTime();
                String timeStamp = String.valueOf(beijingDate.getTime() / 1000);
                SortedMap<String, Object> map2 = new TreeMap<String, Object>();
                map2.put("appid", sysConfig.getConfigValue());
                map2.put("timestamp", timeStamp);
                map2.put("noncestr", wxData.GetValue("nonce_str"));
                map2.put("prepayid", wxData.GetValue("prepay_id"));
                map2.put("package", "Sign=WXPay");
                map2.put("partnerid", wxData.GetValue("mch_id"));
                String paySign = WxPayApi.createSign(map2, sysConfig.getConfigRules());
                map2.put("sign", paySign);
                respVo.setCode(RespVo.CODE_SUCCESS);
                respVo.setResult(map2);
                OrderQueryMQ orderQueryMQ = OrderQueryMQ.builder().orderId(orderNum).queryTimes(0L).build();
                orderQueryMQ.setPayType(PayType.wx);
                orderQueryMQ.setBody(body);
                orderQueryMQ.setTraceId(MDCUtil.getTraceId());
                messageService.sendAndQueryTimes(AmqpExchange.ORDER_QUERY_MESSAGE, orderQueryMQ, orderQueryMQ.getQueryTimes());
            } else {
                respVo.setCode(RespVo.CODE_ERROR);
                respVo.setMessage("发起微信支付失败");
            }
        } catch (Exception e) {
            log.error("调用微信支付请求异常：", e);
            respVo.setCode(RespVo.CODE_ERROR);
            respVo.setMessage("发起微信支付失败");
        }

        return respVo;
    }

    /**
     * 确认收货
     *
     * @param order
     * @return
     */
    @RequestMapping("/updateSendStatus")
    @ResponseBody
    public RespVo updateSendStatus(SpellOrder order) {
        log.info("确认收货:{}", JSON.toJSONString(order));

        RespVo vo = new RespVo();
        try {
            spellOrderService.updateById(order);
            vo.setCode(RespVo.CODE_SUCCESS);
            vo.setMessage("确认收货成功");
        } catch (Exception e) {
            vo.setCode(RespVo.CODE_ERROR);
            vo.setMessage("确认收货失败");
            log.error("确认收货失败", e);
        }
        return vo;
    }

    @SuppressWarnings("rawtypes")
    @PostMapping("/alipayNotify")
    public void appAliPayNotify(HttpServletRequest request, HttpServletResponse response) {
        log.info("支付宝回调");
        log.error("============================支付宝回调开始");
        response.setCharacterEncoding("UTF-8");
        //设置字符流编码，而且还会添加content-Type响应头，这个头通知浏览器用utf-8解码。
        response.setContentType("text/html;charset=utf-8");

        Map<String, String> params = new HashMap<String, String>();
        Map requestParams = request.getParameterMap();
        for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
            }
            // 乱码解决，这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化
            // valueStr = new String(valueStr.getBytes("ISO-8859-1"), "gbk");
            params.put(name, valueStr);
        }

        log.error("收到支付宝支付回调，内容：" + JSON.toJSONString(params));
        try {
            // 返回success
            PrintWriter out = response.getWriter();
            out.print("success");
            out.flush();
            out.close();

            // 调用SDK验证签名
            SysConfig sysConfig = sysConfigService.getOne(Wraps.<SysConfig>lbQ().eq(SysConfig::getConfigKey, "aliPaySys").eq(SysConfig::getDisplayStatus, "1"));
            boolean flag = AlipaySignature.rsaCheckV1(params, sysConfig.getConfigRules(), AlipayConfig.CHARSET, AlipayConfig.SIGNTYPE);
            //boolean flag = AlipaySignature.rsaCheckV1(params, AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.CHARSET, AlipayConfig.SIGNTYPE);

            // 商户订单号
            String outTradeNo = new String(request.getParameter("out_order_no").getBytes("ISO-8859-1"), "UTF-8");
            // 支付宝交易号
            String notify_type = new String(request.getParameter("notify_type").getBytes("ISO-8859-1"), "UTF-8");

            String status = new String(request.getParameter("status").getBytes("ISO-8859-1"), "UTF-8");
            log.error("==================notify_type ： " + notify_type);

            if (flag && this.validateOrderNo(outTradeNo) && StringUtils.equals(status, "SUCCESS")) {
                if (StringUtils.equals(notify_type, "fund_auth_freeze")) {
                    //预授权通知
                    String auth_no = new String(request.getParameter("auth_no").getBytes("ISO-8859-1"), "UTF-8");
                    String payer_user_id = new String(request.getParameter("payer_user_id").getBytes("ISO-8859-1"), "UTF-8");
//                    doJoinSpell(outTradeNo, auth_no, payer_user_id);
                } else if (StringUtils.equals(notify_type, "trade_status_sync")) {

                } else if (StringUtils.equals(notify_type, "fund_auth_unfreeze")) {

                }
            }
        } catch (Exception e) {
            log.error("支付宝支付回调异常：", e);
        }
    }


    private boolean validateOrderNo(String orderNo) {
        String order = (String) redisService.get(orderNo);
        if (StringUtils.isBlank(order)) {
            // 将订单号放入redis中60分钟
            redisService.set(orderNo, "60");
            redisService.expire(orderNo, 600L);
            return true;
        }
        return false;
    }
}
